#include "DXUT.h"
#include "RandomNumBuffer.h"
#include "DXHelper.h"
#include "RandomMwc.h"

/**
*/
RandomNumBuffer::RandomNumBuffer() : m_pTexture( NULL ), m_pSRV( NULL ), m_nWidth( 0 ), m_nHeight( 0 )
{
}

/**
*/
RandomNumBuffer::~RandomNumBuffer()
{
}

/**
*/
HRESULT RandomNumBuffer::OnResizedSwapChain( ID3D11Device* pd3dDevice, int nWidth, int nHeight, float fMinRe, float fMaxRe, float fMinIm, float fMaxIm )
{
    HRESULT hr = S_OK;

    m_nWidth = nWidth;
    m_nHeight = nHeight;

    // initialize buffer with 0
    m_data.clear();
    m_data.resize( nWidth*nHeight );
    for( size_t nIndex=0; nIndex<m_data.size(); ++nIndex ) {
        m_data[ nIndex ].x = g_randomMwc.getFloatInRange( fMinRe, fMaxRe );
        m_data[ nIndex ].y = g_randomMwc.getFloatInRange( fMinIm, fMaxIm );
    }
        
    D3D11_TEXTURE2D_DESC desc;
    ZeroMemory( &desc, sizeof( D3D11_TEXTURE2D_DESC ) );
    desc.Width = nWidth;
    desc.Height = nHeight;
    desc.MipLevels = 1;
    desc.Format = DXGI_FORMAT_R32G32_FLOAT;
    desc.Usage = D3D11_USAGE_DYNAMIC;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    desc.SampleDesc.Count = 1;
    desc.ArraySize = 1;
    pd3dDevice->CreateTexture2D( &desc, NULL, &m_pTexture );
    
    // create shader resource views
    D3D11_SHADER_RESOURCE_VIEW_DESC descRV;
    descRV.Format = desc.Format;
    descRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    descRV.Texture2D.MipLevels = 1;
    descRV.Texture2D.MostDetailedMip = 0;
    V_RETURN( pd3dDevice->CreateShaderResourceView( m_pTexture, &descRV, &m_pSRV) );
    
    return hr;
}

/**
*/
void RandomNumBuffer::OnDestroyDevice()
{
    SAFE_RELEASE( m_pTexture );
    SAFE_RELEASE( m_pSRV );
}

/**
    @param pd3dDevice                [in]            D3D Device
    @param pd3dImmediateContext        [in]            D3D Device Immediate Context
*/
void RandomNumBuffer::UpdateBuffer( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, float fMinRe, float fMaxRe, float fMinIm, float fMaxIm )
{
    for( size_t nIndex=0; nIndex<m_data.size(); ++nIndex ) {
        m_data[ nIndex ].x = g_randomMwc.getFloatInRange( fMinRe, fMaxRe );
        m_data[ nIndex ].y = g_randomMwc.getFloatInRange( fMinIm, fMaxIm );
    }

    D3D11_MAPPED_SUBRESOURCE mappedResource;
    pd3dImmediateContext->Map( m_pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource );
    unsigned char* pData = reinterpret_cast< unsigned char* >( mappedResource.pData );
    // copy data one row at a time, taking into consideration the mapped surface pitch info.
    for( int nRow=0; nRow<m_nHeight; ++nRow )
    {
        memcpy( pData, &m_data[ nRow*m_nWidth ], m_nWidth*sizeof(m_data[0]) );
        pData += mappedResource.RowPitch;
    }
    pd3dImmediateContext->Unmap( m_pTexture, 0 );
}
